//
//  demo1.cpp
//  OpenGLDemo
//
//  Created by 樊星 on 2020/4/15.
//  Copyright © 2020 樊星. All rights reserved.
//

#include "demo1.hpp"

//GLTool.h头文件包含了大部分GLTool中类似C语言的独立函数
#include "GLTools.h"

//在Mac系统下，‘#include<glut/glut.h>’，在Windows和Linux上，我们使用freeglut的静态库版本并且需要添加一个宏
#include <GLUT/GLUT.h>


//简单的批次容器，是GLTools的一个简单的容器类。
GLBatch triangleBatch;

//定义⼀个，着⾊管理器
GLShaderManager shaderManager;

//自定义函数，通过glutReshaperFunc(函数名)注册为重塑函数，当屏幕大小发生变化/护着第一次创建窗口时，会调用该函数调整窗口大小、视口大小
//窗口大小改变时接收新的宽度和高度，其中0，0代表窗口中视口的左下角坐标，w，h带包像素
/*
 changeSize 触发条件：
 1. 新建窗口
 2. 窗口尺寸发生调整
 
 处理业务：
 1. 设置OpenGL 视口
 2. 设置OpenGL 投影方式
 */
void ChangeSize(int width, int height){
    
    glViewport(0, 0, width, height);
}


//自定义函数，设置你需要渲染的图形的相关顶点数据/颜色数据等数据装备工作
//为程序做一次性的设置
/*
 setupRC触发条件：
 1. 手动main函数触发
 
 处理业务：
 1. 设置窗口背景色
 2. 初始化存储着色器shaderManager
 3. 设置图形顶点数据
 4. 利用GLBatch三角形批次类，将数据传递到着色器
 */
void setupRC(){
    
    //设置背景颜色
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
    //初始化着色器管理器
    shaderManager.InitializeStockShaders();
    
    //设置三角形，其中数组vVert包含所有3个顶点的x,y 笛卡尔坐标对。
    GLfloat vVerts[] = {
        
        -0.5f, 0.0f, 0.0f,
        
        0.5f, 0.0f, 0.0f,
        
        0.0f, 0.5f, 0.0f,
    };
    
    //批次处理
    triangleBatch.Begin(GL_TRIANGLES, 3);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}


//自定义函数，通过glutDisplayFunc(函数名)注册为显示渲染函数，当屏幕发生变化/或者开发者主动渲染会调用此函数，用来实现数据->渲染过程
//开始渲染
/*
 RenderScene 触发条件：
 1. 系统自动触发
 2. 开发者手动调用函数触发
 
 处理业务：
 1. 清除缓冲区（颜色，深度，模板缓冲区等）
 2. 使用存储着色器
 3. 绘制图形
 */
void RenderScene(void){
    
    //清除一个或一组特定的缓冲区
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    GLfloat vRed[] = {1.0, 0.0, 0.0, 1.0f};
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
    triangleBatch.Draw();
    glutSwapBuffers();
}


//main 函数：程序入口.OpenGL 是面向过程编程，所以你会发现利用OpenGL处理图形/图像都是链式形式，以及基于OpenGL封装的图像处理框架也是链式编程
void demo1Init(int argc, char *argv[]){
    
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
    
    glutInitWindowSize(800, 600);
    
    glutCreateWindow("Triangle");
    
    glutReshapeFunc(ChangeSize);
    
    glutDisplayFunc(RenderScene);
    
    GLenum status = glewInit();
    
    if (GLEW_OK != status) {
        printf("GLEW Error:%s\n", glewGetErrorString(status));
    }
    
    setupRC(); //设置数据
    glutMainLoop(); //类似于iOS runloop运行循环
}
